/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.repository.adaptor.method.setentityvalue;

//import Inspur.Ecp.Caf.DataAccess.*;
//import Inspur.Gsp.Caf.Generator.BaseInfoItem.*;
//import Inspur.Gsp.Caf.Generator.ClassMethodGenerator.*;
//import Inspur.Gsp.Caf.Generator.Utils.*;
//import Inspur.Gsp.Cef.Api.Attribute.*;
//import Inspur.Gsp.Cef.Api.Repository.*;
//import Inspur.Gsp.Cef.Entity.*;
//import Inspur.Gsp.Cef.Repository.*;
//import Inspur.Gsp.Cef.Repository.ReaderWriter.*;
//import Microsoft.CodeAnalysis.*;
//import Microsoft.CodeAnalysis.CSharp.*;
//import Microsoft.CodeAnalysis.CSharp.Syntax.*;
//import Inspur.Gsp.Cef.RTGenerator.Common.*;
//import Inspur.Gsp.Cef.Spi.Entity.*;
//import Inspur.Gsp.Cef.RTGenerator.RepositoryGen.*;

import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.cef.api.repository.readerWriter.ICefReader;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.generator.coreGenerator.entityGenerator.CommonModelCoreGeneratorContext;
import com.inspur.edp.cef.generator.repository.adaptor.method.createpropertydefmethod.CreateUdtDefMethodGenerator;
import com.inspur.edp.cef.generator.repository.adaptor.method.createpropertydefmethod.EntityCreateAssocationDefMethodGenerator;
import com.inspur.edp.cef.generator.repository.adaptor.method.createpropertydefmethod.EntityCreateEnumDefMethodGenerator;
import com.inspur.edp.cef.generator.repository.adaptor.method.createpropertydefmethod.NormalPropertyCreateDefMethodGenerator;
import com.inspur.edp.cef.generator.repository.dac.DataTypeDacGenContext;
import com.inspur.edp.cef.repository.dbcolumninfo.DbColumnInfo;
import com.inspur.edp.cef.repository.dbcolumninfo.DbColumnInfoCollection;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import org.eclipse.jdt.core.dom.*;

import java.util.ArrayList;

public abstract class SetEntityValueGenerator extends ClassMethodGenerator {
	protected static final String RecordParamName = "reader";
	protected static final String RecordParamDataName = "entityData";
	public static String EntityVarName = "entity";
	protected static final String ReadVarName = "%1$sReader";
	protected static final String MgrVarName = "%1$sManager";
	protected static final String ReposVarName = "%1$srepository";
	protected static final String PropEntityVarName = "%1$sentity";
	protected DataTypeDacGenContext dacContext;
	private IGspCommonDataType gspCommonDataType;
	//Key:propertyName, Value:PropName
	private java.util.HashMap<String, String> mappingPropNames;
//	private DbColumnInfoCollection dbColumns;

	public SetEntityValueGenerator(DataTypeDacGenContext dacContext, IGspCommonDataType gspCommonDataType, java.util.HashMap<String, String> mappingPropNames, DbColumnInfoCollection dbColumns) {
		this.dacContext = dacContext;
		this.gspCommonDataType = gspCommonDataType;
		this.mappingPropNames = mappingPropNames;
//		this.dbColumns = dbColumns;
	}

	@Override
	protected String getMethodName() {
		return "setEntityValue";
	}

	@Override
	protected TypeInfo getReturnType() {
		return null;
	}

	@Override
	protected boolean getIsOverride() {
		return true;
	}

	@Override
	protected ArrayList<Modifier.ModifierKeyword> getAccessModifiers() {
		return new ArrayList<Modifier.ModifierKeyword>(java.util.Arrays.asList(new Modifier.ModifierKeyword[]{Modifier.ModifierKeyword.PROTECTED_KEYWORD}));
	}

	@Override
	protected ArrayList<ParameterInfo> getParameterCollection() {
		ArrayList<ParameterInfo> list =new ArrayList<ParameterInfo>();
		ParameterInfo parameterInfo=new ParameterInfo();
		parameterInfo.setParamType(new TypeInfo(ICefReader.class));
		parameterInfo.setParamName(RecordParamName);
		list.add(parameterInfo);

		ParameterInfo parameterdataInfo=new ParameterInfo();
		parameterdataInfo.setParamType(new TypeInfo(IEntityData.class));
		parameterdataInfo.setParamName(RecordParamDataName);
		list.add(parameterdataInfo);
		return list;
	}

	@Override
	protected Block buildMethodBody() {
		Block block=ast.newBlock();
		String entityTypeName = buildEntityTypeName();
		addNewDataStatement(block,entityTypeName);
		addSetPropertiesStatements(block,entityTypeName);
		return block;
	}
	protected String buildEntityTypeName()
	{
		return ((CommonModelCoreGeneratorContext) dacContext.getReposContext().getCefContext().getCefGenContext().getCoreGenContext()).getEntityDataMediateTypes().get("RootNode").getClassName();
	}

	private void addNewDataStatement(Block block, String entityTypeName) {
		VariableDeclarationFragment variableDeclarationFragment=ast.newVariableDeclarationFragment();
		variableDeclarationFragment.setName(ast.newSimpleName("entity"));
		CastExpression castExpression = ast.newCastExpression();
		castExpression.setType(ast.newSimpleType(ast.newSimpleName(entityTypeName)));
		castExpression.setExpression(ast.newSimpleName("entityData"));
		variableDeclarationFragment.setInitializer(castExpression);
		VariableDeclarationStatement variableDeclarationStatement=ast.newVariableDeclarationStatement(variableDeclarationFragment);
		variableDeclarationStatement.setType(ast.newSimpleType(ast.newName(entityTypeName)));
		block.statements().add(variableDeclarationStatement);
	}

	private void addSetPropertiesStatements(Block block, String entityTypeName)
	{

		for(IGspCommonField gspCommonField: gspCommonDataType.getContainElements()){
			addSetPropertyStatement(gspCommonField, block,entityTypeName);
		}
	}

	protected  void addSetPropertyStatement(IGspCommonField gspCommonField, Block block, String entityTypeName)
	{
//		Class childAttrType = dacContext.getReposContext().getCefContext().childAttrType();
//		Object childAttribute = ReflectionUtils.getMethodAnnotation(propertyInfo.getPropertyMethod(),childAttrType);
//
//		Class dataTypeAttrType = dacContext.getReposContext().getCefContext().dataTypeAttrType();
//		Object dataTypeAttribute =  ReflectionUtils.getMethodAnnotation(propertyInfo.getPropertyMethod(),dataTypeAttrType);
//
//		Class extendChildAttrType = dacContext.getReposContext().getCefContext().extendChildAttribute();
//		Object extendChildAttribute = ReflectionUtils.getMethodAnnotation(propertyInfo.getPropertyMethod(),extendChildAttrType);
//
//		if (extendChildAttribute != null || childAttribute != null) {
//			return;
//		}
		if(gspCommonField.getIsVirtual() || gspCommonField.getObjectType() == GspElementObjectType.DynamicProp)
			return;
		if(gspCommonField.getIsUdt()){
			buildUdtPropertyStatement(gspCommonField, block);
		}
		else {
			IfStatement ifStatement=createIfStatement(block,gspCommonField);
			Block block1=ast.newBlock();
			ifStatement.setThenStatement(block1);
			buildEntityPropertyStatement(gspCommonField, block1);
		}

	}

	private IfStatement createIfStatement(Block block,IGspCommonField gspCommonField)
	{
		IfStatement ifStatement=ast.newIfStatement();
		MethodInvocation methodInvocation=ast.newMethodInvocation();
		methodInvocation.setExpression(ast.newSimpleName("reader"));
		methodInvocation.setName(ast.newSimpleName("hasProperty"));
		StringLiteral stringLiteral=ast.newStringLiteral();
		stringLiteral.setLiteralValue(gspCommonField.getLabelID());
		methodInvocation.arguments().add(stringLiteral);

		ifStatement.setExpression(methodInvocation);
		block.statements().add(ifStatement);
		return ifStatement;
	}

	private void buildEntityPropertyStatement(IGspCommonField gspCommonField, Block block) {
		String propertyName = gspCommonField.getLabelID();
//		if (!dbColumns.contains(propertyName)) {
//			return;
//		}

//		DbColumnInfo columnInfo = dbColumns.getItem(propertyName);


		if (gspCommonField.getObjectType() == GspElementObjectType.Association) {
			addAssociationStatement(gspCommonField, block);
			return;
		}
		if (gspCommonField.getIsRef()) {
			return;
		}
		if (gspCommonField.getObjectType() == GspElementObjectType.Enum) {
			addEnumStatement(gspCommonField, block);
			return;
		}

		addNormalStatement(gspCommonField, EntityVarName, block);
	}

	private void addAssociationStatement(IGspCommonField gspCommonField, Block block) {


		MethodInvocation methodInvocation=ast.newMethodInvocation();
		methodInvocation.setName(ast.newSimpleName("set" + gspCommonField.getLabelID()));
		methodInvocation.setExpression(ast.newSimpleName(EntityVarName));

		MethodInvocation methodInvocationGetProValue = ast.newMethodInvocation();
		methodInvocationGetProValue.setName(ast.newSimpleName(EntityCreateAssocationDefMethodGenerator.getAssPropertyValueMethodName(gspCommonField.getLabelID())));
		methodInvocationGetProValue.arguments().add(ast.newSimpleName(RecordParamName));

		methodInvocation.arguments().add(methodInvocationGetProValue);
		block.statements().add(ast.newExpressionStatement(methodInvocation));
	}

	private void addEnumStatement(IGspCommonField gspCommonField, Block block)
	{
		MethodInvocation methodInvocation=ast.newMethodInvocation();
		methodInvocation.setName(ast.newSimpleName("set" + gspCommonField.getLabelID()));
		methodInvocation.setExpression(ast.newSimpleName(EntityVarName));

		MethodInvocation methodInvocationGetProValue = ast.newMethodInvocation();
		methodInvocationGetProValue.setName(ast.newSimpleName(EntityCreateEnumDefMethodGenerator.getEnumPropertyValueMethodName(gspCommonField.getLabelID())));
		methodInvocationGetProValue.arguments().add(ast.newSimpleName(RecordParamName));

		methodInvocation.arguments().add(methodInvocationGetProValue);
		block.statements().add(ast.newExpressionStatement(methodInvocation));
	}

	protected  void addNormalStatement(IGspCommonField gspCommonField, String entityVarName, Block block)
	{
		MethodInvocation methodInvocation=ast.newMethodInvocation();
		methodInvocation.setName(ast.newSimpleName("set" +gspCommonField.getLabelID()));
		methodInvocation.setExpression(ast.newSimpleName(EntityVarName));

		MethodInvocation methodInvocationGetProValue = ast.newMethodInvocation();
		methodInvocationGetProValue.setName(ast.newSimpleName(NormalPropertyCreateDefMethodGenerator.getMethodName(gspCommonField.getLabelID())));
		methodInvocationGetProValue.arguments().add(ast.newSimpleName(RecordParamName));

		methodInvocation.arguments().add(methodInvocationGetProValue);
		block.statements().add(ast.newExpressionStatement(methodInvocation));
	}


	protected  void buildUdtPropertyStatement(IGspCommonField gspCommonField, Block block)
	{
		MethodInvocation methodInvocation=ast.newMethodInvocation();
		methodInvocation.setName(ast.newSimpleName("set" + gspCommonField.getLabelID()));
		methodInvocation.setExpression(ast.newSimpleName(EntityVarName));

		MethodInvocation methodInvocationGetProValue = ast.newMethodInvocation();
		methodInvocationGetProValue.setName(ast.newSimpleName(CreateUdtDefMethodGenerator.getUdtPropertyMethodName(gspCommonField.getLabelID())));
		methodInvocationGetProValue.arguments().add(ast.newSimpleName(RecordParamName));

		methodInvocation.arguments().add(methodInvocationGetProValue);
		block.statements().add(ast.newExpressionStatement(methodInvocation));
	}
}
